home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / dev / m2 / m2_part1.lha / modula / dice / dice.LHA / cc / main.c < prev    next >
C/C++ Source or Header  |  1991-04-24  |  27KB  |  1,411 lines

  1.  
  2. /*
  3.  *  MAIN.C
  4.  *
  5.  *  (c)Copyright 1990, Matthew Dillon, All Rights Reserved
  6.  *
  7.  *  dcc <options> <files>
  8.  */
  9.  
  10. #include "defs.h"
  11.  
  12. #ifndef AZLAT_COMPAT
  13. #define DoLink_Dice    DoLink
  14. #define DoCompile_Dice    DoCompile
  15. #define DoAssemble_Dice DoAssemble
  16. #define DoPrelink_Dice    DoPrelink
  17. #endif
  18.  
  19. #ifdef _DCC
  20. IDENT("DCC",".21");
  21. DCOPYRIGHT;
  22. #endif
  23.  
  24. Prototype   void    myexit(void);
  25. Prototype   int     main(int, char **);
  26. Prototype   void    AddFile(char *);
  27. Prototype   void    help(int);
  28. Prototype   char    *TmpFileName(char *);
  29. Prototype   char    *MungeFile(char *, char *, char *);
  30. Prototype   void    AddName(LIST *, char *, char *);
  31. Prototype   void    AddOpt(LIST *, char *, char *);
  32. Prototype   char    *Tailer(char *);
  33. Prototype   char    *XFilePart(char *);
  34. Prototype   char    *OptListToStr(LIST *);
  35. Prototype   char    *OptListToStr2(LIST *, char *);
  36. Prototype   void    run_cmd(char *);
  37. Prototype   int     OutOfDate(char *, char *);
  38. Prototype   void    HandleCFile(char *, int);
  39. Prototype   void    HandleAFile(char *, int);
  40. Prototype   void    PushTmpFile(char *);
  41. Prototype   void    PopTmpFile(char *);
  42. Prototype   long    LoadSegLock(long);
  43.  
  44. Prototype   int     DoCompile(char *, char *);
  45. Prototype   int     DoCompile_Dice(char *, char *);
  46. Prototype   int     DoCompile_Aztec(char *, char *);
  47. Prototype   int     DoCompile_Lattice(char *, char *);
  48. Prototype   int     DoAssemble(char *, char *);
  49. Prototype   int     DoAssemble_Dice(char *, char *);
  50. Prototype   int     DoAssemble_Aztec(char *, char *);
  51. Prototype   int     DoAssemble_Lattice(char *, char *);
  52. Prototype   char    *DoPrelink(void);
  53. Prototype   char    *DoPrelink_Dice(void);
  54. Prototype   char    *DoPrelink_Aztec(void);
  55. Prototype   char    *DoPrelink_Lattice(void);
  56. Prototype   int     DoLink(char *);
  57. Prototype   int     DoLink_Dice(char *);
  58. Prototype   int     DoLink_Aztec(char *);
  59. Prototype   int     DoLink_Lattice(char *);
  60.  
  61. /*
  62.  *  Note that we use exec_dcc if DCC, which only works with 'dcc' programs
  63.  *  thus, the executables are renamed to prevent problems.
  64.  */
  65.  
  66. Prototype __aligned char Buf[512];
  67.  
  68.  
  69. __aligned char Buf[512];
  70. char TmpFile[64];
  71. char ErrOptStr[128];
  72. char *ErrFile;
  73. char *OutFile;
  74. char *OutDir = "T:";
  75. char *TmpDir = "T:";
  76. char *AmigaLib = "dlib:amigas";
  77. char *AmigaLibApp1 = "";
  78. char *AmigaLibApp2 = "";
  79. char *CLib = "dlib:c";
  80. char *CLibApp = "";
  81. LIST TmpList;
  82. short NewOpt;
  83. short FastOpt;
  84. short FragOpt;
  85. short ChipOpt;
  86. short MC68020Opt;
  87. short MC68881Opt;
  88. short FFPOpt;
  89. short DDebug;
  90. short RegCallOpt;
  91. short NoHeirOpt;
  92.  
  93. char DLINK[32];
  94. char DAS[32];
  95. char DC1[32];
  96. char DCPP[32];
  97.  
  98. typedef struct NameNode {
  99.     struct Node n_Node;
  100.     char    *n_In;
  101.     char    *n_Out;
  102.     short   n_IsTmp;
  103. } NameNode;
  104.  
  105. LIST   CList;
  106. LIST   AList;
  107. LIST   OList;
  108. LIST   LList;
  109.  
  110. LIST   CppOptList;
  111. LIST   LinkOptList;
  112.  
  113. short    NoLink;
  114. short    NoAsm;
  115. short    SmallCode = 1;
  116. short    SmallData = 1;
  117. short    ConstCode;        /*    -ms            */
  118. short    AbsData;        /*    -mw, -ma        */
  119. short    ResOpt;
  120. short    AltSectOpt;
  121. short    SymOpt;
  122. short    RomOpt;
  123. short    ProtoOnlyOpt;
  124. short    NoIntermediateAssembly;
  125. short    PIOpt;
  126. short    GenStackOpt;
  127. short    GenLinkOpt;
  128. short    Verbose;
  129. short    NoDefaultLibs;
  130. short    CompilerOpt = DICE_C;
  131. long    AbsDataStart;        /*    -mw <addr>  */
  132. char    DebugOpts[64];
  133.  
  134. extern struct Library *SysBase;
  135.  
  136. void
  137. myexit()
  138. {
  139.     NODE *node;
  140.  
  141.     while (node = RemHead(&TmpList)) {
  142.     remove(node->ln_Name);
  143.     free(node);
  144.     }
  145. }
  146.  
  147. int
  148. main(xac, xav)
  149. int xac;
  150. char *xav[];
  151. {
  152.     int fc = 0;
  153.     int ac;
  154.     char **av;
  155.  
  156. #ifdef LATTICE
  157.     {
  158.     long n = (long)Buf;
  159.     if (n & 3) {
  160.         puts("software error, Buf not aligned");
  161.         exit(1);
  162.     }
  163.     }
  164. #endif
  165. #ifdef NOTDEF
  166.     expand_args(xac, xav, &ac, &av);
  167. #else
  168.     ac = xac;
  169.     av = xav;
  170. #endif
  171.  
  172.     NewList(&CList);
  173.     NewList(&AList);
  174.     NewList(&OList);
  175.     NewList(&LList);
  176.  
  177.     NewList(&TmpList);
  178.  
  179.     NewList(&CppOptList);
  180.     NewList(&LinkOptList);
  181.  
  182.     atexit(myexit);
  183.  
  184.     if (ac == 1)
  185.     help(0);
  186.  
  187.     {
  188.     char *ptr = av[0];    /*  cmd name */
  189.     char prefix[32];
  190.     short i;
  191.  
  192.     for (i = strlen(ptr); i >= 0 && ptr[i] != ':' && ptr[i] != '/'; --i);
  193.     ++i;
  194.  
  195.     ptr = ptr + i;        /*  base name */
  196.     for (i = 0; ptr[i] && ptr[i] != '_'; ++i);
  197.     if (ptr[i] == '_') {
  198.         strncpy(prefix, ptr, i + 1);
  199.         prefix[i+1] = 0;
  200.     } else {
  201.         prefix[0] = 0;
  202.     }
  203.     sprintf(DLINK, "%s%s", prefix, "dlink");
  204.     sprintf(DAS  , "%s%s", prefix, "das");
  205.     sprintf(DC1  , "%s%s", prefix, "dc1");
  206.     sprintf(DCPP , "%s%s", prefix, "dcpp");
  207.     }
  208.  
  209.     {
  210.     char **argv = av;
  211.     ac = ExtArgsEnv(ac, &argv, "ENV:DCCOPTS");
  212.     av = argv;
  213.     }
  214.  
  215.     {
  216.     long i;
  217.     char *dummy;
  218.  
  219.     for (i = 1; i < ac; ++i) {
  220.         char *ptr = av[i];
  221.  
  222.         if (*ptr == '-') {
  223.         ptr += 2;
  224.  
  225.         switch(ptr[-1]) {
  226.         case '0':       /*  -020        */
  227.             MC68020Opt = 1;
  228.             break;
  229.         case '1':       /*  1.4, 1.3    */
  230.         case '2':       /*  2.0, 2.1..  */
  231.             if (ptr[0] != '.')
  232.             help(1);
  233.             AddOpt(&CppOptList, ptr - 2, "");
  234.             {
  235.             static char ABuf[32];
  236.  
  237.             sprintf(ABuf, "%c%c", ptr[-1], ptr[1]);
  238.             AmigaLibApp2 = ABuf;
  239.             }
  240.             break;
  241.         case '8':
  242.             MC68881Opt = 1;
  243.             break;
  244.         case 'f':
  245.             if (*ptr == 0)
  246.             FastOpt = 1;
  247.             else if (*ptr == 'r')
  248.             FragOpt = 1;
  249.             else if (*ptr == 'f')
  250.             FFPOpt = 1;
  251.             break;
  252.         case 'r':
  253.             if (strcmp(ptr, "om") == 0) {
  254.             RomOpt = 1;
  255.             } else {
  256.             if (PIOpt && ResOpt == 0)
  257.                 puts("DCC: Warning, -r -pi = -pr");
  258.             ResOpt = 1;
  259.             }
  260.             break;
  261.         case 'c':
  262.             if (*ptr == 0)
  263.             NoLink = 1;
  264.             else if (stricmp(ptr, "hip") == 0)
  265.             ChipOpt = 1;
  266.             else
  267.             help(1);
  268.             break;
  269.         case 'a':
  270.             if (strcmp(ptr, "ztec") == 0) {
  271.             CompilerOpt = AZTEC_C;
  272.             break;
  273.             }
  274.             NoAsm = 1;
  275.             NoLink= 1;
  276.             break;
  277.         case 'g':
  278.             switch (*ptr) {
  279.             case 's':
  280.             GenStackOpt = 1;
  281.             break;
  282.             case 'l':
  283.             GenLinkOpt = 1;
  284.             break;
  285.             default:
  286.             help(1);
  287.             }
  288.             break;
  289.         case 'l':
  290.             if (strcmp(ptr, "attice") == 0) {
  291.             CompilerOpt = LATTICE_C;
  292.             break;
  293.             }
  294.             if (ptr[0] == '0' && ptr[1] == 0) {
  295.             NoDefaultLibs = 1;
  296.             break;
  297.             }
  298.             if (*ptr == 0)
  299.             ptr = av[++i];
  300.             AddName(&LList, ".lib", ptr);
  301.             break;
  302.         case 'L':   /*  -Idir   */
  303.             if (ptr[0] == '0' && ptr[1] == 0) {
  304.             AddOpt(&LinkOptList, "-L0", "");
  305.             break;
  306.             }
  307.             if (*ptr == 0)
  308.             ptr = av[++i];
  309.             AddOpt(&LinkOptList, "-L", ptr);
  310.             break;
  311.         case 'I':   /*  -Idir   */
  312.             if (ptr[0] == '0' && ptr[1] == 0) {
  313.             AddOpt(&CppOptList, "-I0", "");
  314.             break;
  315.             }
  316.             if (*ptr == 0)
  317.             ptr = av[++i];
  318.             AddOpt(&CppOptList, "-I", ptr);
  319.             break;
  320.         case 'd':   /*  -dice -d<n> -d<debug_opts>  */
  321.             if (strcmp(ptr, "ice") == 0) {
  322.             CompilerOpt = DICE_C;
  323.             break;
  324.             }
  325.             if (atoi(ptr)) {
  326.             DDebug = atoi(ptr);
  327.             break;
  328.             }
  329.             sprintf(DebugOpts, " -d%s", ptr);
  330.             break;
  331.         case 'D':   /*  -Ddefine[=str] */
  332.             if (*ptr == 0)
  333.             ptr = av[++i];
  334.             AddOpt(&CppOptList, "-D", ptr);
  335.             break;
  336.         case 'U':   /*  -U      -undefine certain symbols */
  337.             AddOpt(&CppOptList, "-U", ptr);
  338.             break;
  339.         case 'o':
  340.             if (*ptr)
  341.             OutFile = ptr;
  342.             else
  343.             OutFile = av[++i];
  344.             {
  345.             short idx = strlen(OutFile) - 2;
  346.             if (idx >= 0) {
  347.                 if (stricmp(OutFile + idx, ".h") == 0 || stricmp(OutFile + idx, ".c") == 0) {
  348.                 puts("ERROR! -o output file may not end in .c or .h!");
  349.                 exit(20);
  350.                 }
  351.             }
  352.             }
  353.             break;
  354.         case 'O':
  355.             if (*ptr)
  356.             OutDir = ptr;
  357.             else
  358.             OutDir = av[++i];
  359.             break;
  360.         case 'E':   /*  error output append */
  361.             if (*ptr == 0)
  362.             ptr = av[++i];
  363.  
  364.             if (freopen(ptr, "a", stderr)) {
  365.             ErrFile = ptr;
  366.             sprintf(ErrOptStr," -E %s", ptr);
  367.             } else {
  368.             printf("unable to append to %s\n", ptr);
  369.             }
  370.             break;
  371.         case 'p':
  372.             if (strcmp(ptr, "roto") == 0) {
  373.             ProtoOnlyOpt = 1;
  374.             } else if (strcmp(ptr, "i") == 0) {
  375.             PIOpt = 1;
  376.             if (ResOpt)
  377.                 puts("DCC: Warning, -r -pi = -pr");
  378.             } else if (strcmp(ptr, "r") == 0) {
  379.             PIOpt = 1;
  380.             ResOpt = 1;
  381.             } else {
  382.             help(1);
  383.             }
  384.             break;
  385.         case 'T':
  386.             if (*ptr)
  387.             TmpDir = ptr;
  388.             else
  389.             TmpDir = av[++i];
  390.             break;
  391.         case 'm':
  392.             switch(*ptr) {
  393.             case 'C':
  394.             SmallCode = 0;
  395.             break;
  396.             case 'c':
  397.             SmallCode = 1;
  398.             break;
  399.             case 'D':
  400.             SmallData = 0;
  401.             break;
  402.             case 'd':
  403.             SmallData = 1;
  404.             break;
  405.             case 'a':
  406.             case 'w':
  407.             AbsData = 1;
  408.  
  409.             if (*ptr == 'a')
  410.                 AbsData = 2;
  411.  
  412.             ++ptr;
  413.             if (*ptr == 0)
  414.                 ptr = av[++i];
  415.  
  416. #ifdef LATTICE
  417.             AbsDataStart = atoi(ptr);   /*  bug in lattice */
  418. #else
  419.             AbsDataStart = strtol(ptr, &dummy, 0);
  420. #endif
  421.             break;
  422.             case 'r':
  423.             RegCallOpt = 1;
  424.             break;
  425.             case 'R':
  426.             CLibApp = "r";
  427.             AmigaLibApp1 = "r";
  428.             RegCallOpt = 2;
  429.             if (ptr[1] == 'R') {
  430.                 RegCallOpt = 3;
  431.                 if (ptr[2] == 'X')
  432.                 RegCallOpt = 4;
  433.             }
  434.             break;
  435.             case 's':
  436.             if (strcmp(ptr, "as") == 0) {
  437.                 CompilerOpt = LATTICE_C;
  438.                 break;
  439.             }
  440.             if (ptr[1] == '0')
  441.                 ConstCode = 0;
  442.             else
  443.                 ConstCode = 1;
  444.             break;
  445.             case 'S':
  446.             ConstCode = 2;
  447.             break;
  448.             default:
  449.             fprintf(stderr, "bad -s model\n");
  450.             exit(1);
  451.             }
  452.             break;
  453.         case 's':
  454.             SymOpt = 1;
  455.             break;
  456.         case 'S':
  457.             AltSectOpt = 1;
  458.             break;
  459.         case 'v':
  460.             Verbose = 1;
  461.             break;
  462.         case 'n':
  463.             if (strcmp(ptr-1, "new") == 0) {
  464.             NewOpt = 1;
  465.             break;
  466.             }
  467.             if (strcmp(ptr-1, "noheir") == 0) {
  468.             NoHeirOpt = 1;
  469.             break;
  470.             }
  471.             /* fall through */
  472.         default:
  473.             fprintf(stderr, "bad option\n");
  474.             help(1);
  475.         }
  476.         continue;
  477.         }
  478.         if (*ptr == '@') {
  479.         FILE *fi = fopen(ptr + 1, "r");
  480.         char buf[128];
  481.  
  482.         if (fi == NULL) {
  483.             printf("unable to open %s\n", ptr + 1);
  484.             exit(1);
  485.         }
  486.         while (fgets(buf, sizeof(buf), fi)) {
  487.             short len = strlen(buf);
  488.             if (len > 0)
  489.             buf[len-1] = 0;
  490.             if (buf[0] && buf[0] != ';' && buf[0] != '#') {
  491.             ++fc;
  492.             AddFile(buf);
  493.             }
  494.         }
  495.         fclose(fi);
  496.         continue;
  497.         }
  498.         ++fc;
  499.         AddFile(ptr);
  500.     }
  501.     if (i > ac) {
  502.         fprintf(stderr, "file argument missing\n");
  503.         help(1);
  504.     }
  505.     }
  506.  
  507. #ifdef AZLAT_COMPAT
  508.     if (CompilerOpt == AZTEC_C) {
  509.     puts("DCC in AZTEC mode");
  510.     FastOpt = 0;
  511.     NoIntermediateAssembly = 1;
  512.     }
  513.     if (CompilerOpt == LATTICE_C) {
  514.     puts("DCC in LATTICE mode");
  515.     FastOpt = 0;
  516.     NoIntermediateAssembly = 1;
  517.     }
  518. #else
  519.     if (CompilerOpt != DICE_C)
  520.     puts("DCC must be recompiled w/ AZLAT_COMPAT defined");
  521. #endif
  522.  
  523.     {
  524.     NameNode *nn;
  525.  
  526.     while (nn = (NameNode *)RemHead(&CList))
  527.         HandleCFile(nn->n_In, fc);
  528.     if (NoAsm == 0) {
  529.         while (nn = (NameNode *)RemHead(&AList))
  530.         HandleAFile(nn->n_In, fc);
  531.     }
  532.     }
  533.  
  534.     if (NoLink == 0) {
  535.     char *lfile = DoPrelink();
  536.     if (lfile)
  537.         PushTmpFile(lfile);
  538.     DoLink(lfile);
  539.     if (lfile) {
  540.         PopTmpFile(lfile);
  541.         remove(lfile);
  542.         free(lfile);
  543.     }
  544.     }
  545.     return(0);
  546. }
  547.  
  548. void
  549. AddFile(ptr)
  550. char *ptr;
  551. {
  552.     char *t = Tailer(ptr);
  553.  
  554.     if (strncmp(t, "a", 1) == 0) {
  555.     AddName(&AList, NULL, ptr);
  556.     } else
  557.     if (strncmp(t, "o", 1) == 0) {
  558.     AddName(&OList, NULL, ptr);
  559.     } else
  560.     if (strncmp(t, "l", 1) == 0) {
  561.     AddName(&LList, NULL, ptr);
  562.     } else {
  563.     AddName(&CList, NULL, ptr);
  564.     }
  565. }
  566.  
  567. DoCompile_Dice(in, out)
  568. char *in;
  569. char *out;
  570. {
  571.     char *qq = "";
  572.     char *cptmp = TmpFileName(".i");
  573.     char *code = (SmallCode) ? " -mc" : " -mC";
  574.     char *data = (SmallData) ? " -md" : " -mD";
  575.     char *rc = qq;
  576.     char *absdata;
  577.     char *concode;
  578.     char *res  = (ResOpt) ? " -r" : qq;
  579.     char *verb = (Verbose) ? " -v" : qq;
  580.     char *optsect = (AltSectOpt) ? " -S" : qq;
  581.     char *protoonly = (ProtoOnlyOpt) ? " -proto" : qq;
  582.     char *mc68020 = (MC68020Opt) ? " -020" : qq;
  583.     char *mc68881 = (MC68881Opt) ? " -881" : qq;
  584.     char *piopt;
  585.     char *ffp = (FFPOpt) ? " -ffp" : qq;
  586.     char *genstack = (GenStackOpt) ? " -gs" : qq;
  587.     char *genlink  = (GenLinkOpt) ? " -gl" : qq;
  588.  
  589.     switch(RegCallOpt) {
  590.     case 1:
  591.     rc = " -mr";
  592.     break;
  593.     case 2:
  594.     rc = " -mR";
  595.     break;
  596.     case 3:
  597.     rc = " -mRR";
  598.     break;
  599.     case 4:
  600.     rc = " -mRRX";
  601.     break;
  602.     }
  603.  
  604.     switch(ConstCode) {
  605.     case 1:
  606.     concode = " -ms";
  607.     break;
  608.     case 2:
  609.     concode = " -mS";
  610.     break;
  611.     default:
  612.     concode = qq;
  613.     break;
  614.     }
  615.  
  616.     switch(AbsData) {
  617.     case 1:
  618.     absdata = " -mw";
  619.     break;
  620.     case 2:
  621.     absdata = " -ma";
  622.     break;
  623.     default:
  624.     absdata = qq;
  625.     break;
  626.     }
  627.  
  628.     if (PIOpt) {
  629.     if (ResOpt)
  630.         piopt = " -pr";
  631.     else
  632.         piopt = " -pi";
  633.     res = qq;
  634.     absdata = qq;
  635.     code = qq;
  636.     data = qq;
  637.     } else {
  638.     piopt = qq;
  639.     }
  640.  
  641.     PushTmpFile(cptmp);
  642.     sprintf(Buf+1, "%s %s -o %s%s%s%s", DCPP, in, cptmp, ErrOptStr, OptListToStr(&CppOptList), ffp);
  643.     run_cmd(Buf+1);
  644.     sprintf(Buf+1, "%s %s -o %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  645.     DC1, cptmp, out, code, data, rc, res, verb,
  646.     optsect, protoonly, concode, absdata, piopt, ErrOptStr,
  647.     mc68020, mc68881, ffp, genstack, genlink, DebugOpts
  648.     );
  649.     run_cmd(Buf+1);
  650.     PopTmpFile(cptmp);
  651.     remove(cptmp);
  652.     free(cptmp);
  653.     return(0);
  654. }
  655.  
  656. DoAssemble_Dice(in, out)
  657. char *in;
  658. char *out;
  659. {
  660.     sprintf(Buf+1, "%s -o%s %s%s", DAS, out, in, ErrOptStr);
  661.     run_cmd(Buf+1);
  662.     return(0);
  663. }
  664.  
  665. char *
  666. DoPrelink_Dice(void)
  667. {
  668.     NameNode *nn;
  669.     char *ltmp = TmpFileName(".lnk");
  670.     FILE *fi = fopen(ltmp, "w");
  671.  
  672.     if (fi == NULL) {
  673.     fprintf(stderr, "couldn't create %s\n", ltmp);
  674.     exit(1);
  675.     }
  676.  
  677.     while (nn = (NameNode *)RemHead(&OList)) {
  678.     fputs(nn->n_In, fi);
  679.     putc('\n', fi);
  680.     }
  681.     while (nn = (NameNode *)RemHead(&LList)) {
  682.     fputs(nn->n_In, fi);
  683.     putc('\n', fi);
  684.     }
  685.     if (RomOpt == 0 && NoDefaultLibs == 0) {
  686.     fprintf(fi, "%s%s.lib", CLib, CLibApp);
  687.     fprintf(fi, " %s%s%s.lib dlib:auto.lib\n", AmigaLib, AmigaLibApp1, AmigaLibApp2);
  688.     }
  689.     fclose(fi);
  690.     return(ltmp);
  691. }
  692.  
  693. /*
  694.  *  dlib:x.o is a special trailer for any autoinit code (in section autoinit,code)
  695.  *  This section is called in sequence just before main() with ac, av pushed on
  696.  *  the stack.    The idea is that any module may reference an autoinit section to
  697.  *  automatically initialize certain aspects of itself without requiring a call
  698.  *  from the main program.
  699.  */
  700.  
  701. DoLink_Dice(lfile)
  702. char *lfile;
  703. {
  704.     char *qq = "";
  705.     char *co = " ";
  706. #ifdef NOTDEF
  707.     char *ro = (NoDefaultLibs) ? qq : "dlib:x.o";
  708. #endif
  709.     char *ro = "dlib:x.o";
  710.     char *symopt = (SymOpt) ? " -s" : qq;
  711.     char *resopt = (ResOpt) ? " -r" : qq;
  712.     char *fragopt= (FragOpt) ? " -frag" : qq;
  713.     char *chipopt= (ChipOpt) ? " -chip" : qq;
  714.     char *piopt;
  715.     char absdata[20];
  716.  
  717.     if (RomOpt == 0 && NoDefaultLibs == 0) {       /*  RomOpt PIOpt ResOpt */
  718.     static char *SCode[] = { "dlib:c.o ",       /*    0      0      0   */
  719.                  "dlib:c.o ",       /*    0      0      1   */
  720.                  "dlib:c_pi.o ",    /*    0      1      0   */
  721.                  "dlib:c_pr.o "     /*    0      1      1   */
  722.                    };
  723.     co = SCode[(short)((PIOpt << 1) | ResOpt)];
  724.     }
  725.  
  726.     if (OutFile == NULL)
  727.     OutFile = "a.out";
  728.  
  729.     if (AbsData) {
  730.     sprintf(absdata, " -ma 0x%lx", AbsDataStart);
  731.     } else {
  732.     absdata[0] = 0;
  733.     }
  734.  
  735.     if (PIOpt) {
  736.     if (ResOpt)
  737.         piopt = " -pr";
  738.     else
  739.         piopt = " -pi";
  740.     resopt = qq;
  741.     if (AbsData) {
  742.         absdata[0] = 0;
  743.         puts("Warning: cannot mix -pi and -ma/-mw");
  744.     }
  745.     } else {
  746.     piopt = qq;
  747.     }
  748.     if (FragOpt) {
  749.     if (ResOpt) {
  750.         puts("Warning: cannot use -frag with -r");
  751.         fragopt = qq;
  752.     }
  753.     }
  754.  
  755.     sprintf(Buf+1, "%s %s @%s %s -o %s%s%s%s%s%s%s%s%s",
  756.     DLINK, co, lfile, ro, OutFile,
  757.     symopt,
  758.     resopt,
  759.     fragopt,
  760.     piopt,
  761.     absdata,
  762.     chipopt,
  763.     OptListToStr(&LinkOptList),
  764.     ErrOptStr
  765.     );
  766.     run_cmd(Buf+1);
  767.     return(0);
  768. }
  769.  
  770.  
  771.  
  772. void
  773. help(code)
  774. {
  775. #ifdef _DCC
  776.     printf("%s\n%s\n", Ident, DCopyright);
  777. #endif
  778.     puts("Refer to DOC/DCC.DOC for options. -f for resident-hack-fast-load");
  779.     exit(code);
  780. }
  781.  
  782. char *
  783. TmpFileName(tail)
  784. char *tail;
  785. {
  786.     char *buf = malloc(strlen(TmpDir) + strlen(tail) + 32);
  787.     char dummy = 0;
  788.  
  789.     sprintf(buf, "%s%06lx%s", TmpDir, (long)&dummy >> 8, tail);
  790.     return(buf);
  791. }
  792.  
  793. char *
  794. MungeFile(file, hdr, tail)
  795. char *file;
  796. char *hdr;
  797. char *tail;
  798. {
  799.     char *base = file;
  800.     char *name;
  801.     short i;
  802.     short hlen = 0;
  803.  
  804.     if (hdr) {
  805.     hlen = strlen(hdr);
  806.     if (base = strchr(base, ':'))
  807.         ++base;
  808.     else
  809.         base = file;
  810. #ifdef NOTDEF
  811.     while (*base && *base != ':' && *base != '/')
  812.         ++base;
  813.     if (*base == 0)
  814.         base = file;
  815.     else
  816.         ++base;
  817. #endif
  818.     } else {
  819.     hdr = "";
  820.     }
  821.     for (i = strlen(base) - 1; i >= 0; --i) {
  822.     if (base[i] == '.')
  823.         break;
  824.     }
  825.     if (i < 0)
  826.     i = strlen(base);
  827.  
  828.     name = malloc(hlen + i + strlen(tail) + 2);
  829.     strcpy(name, hdr);
  830.     if (hlen && hdr[hlen-1] != ':' && hdr[hlen-1] != '/')
  831.     strcat(name, "/");
  832.     sprintf(name + strlen(name), "%.*s%s", i, base, tail);
  833.     return(name);
  834. }
  835.  
  836. void
  837. AddName(list, tailifnone, file)
  838. LIST *list;
  839. char *tailifnone;
  840. char *file;
  841. {
  842.     NameNode *nn = malloc(sizeof(NameNode));
  843.     short i;
  844.  
  845.     for (i = strlen(file) - 1; i >= 0 && file[i] != '.'; --i) {
  846.     if (file[i] == '/' || file[i] == ':')
  847.         i = 0;
  848.     }
  849.  
  850.     if (i < 0 && tailifnone) {
  851.     nn->n_In = malloc(strlen(file) + strlen(tailifnone) + 1);
  852.     sprintf(nn->n_In, "%s%s", file, tailifnone);
  853.     } else {
  854.     nn->n_In = malloc(strlen(file) + 1);
  855.     strcpy(nn->n_In, file);
  856.     }
  857.     nn->n_Out = NULL;
  858.     nn->n_IsTmp = 0;
  859.     AddTail(list, &nn->n_Node);
  860. }
  861.  
  862. void
  863. AddOpt(list, opt, body)
  864. LIST *list;
  865. char *opt;
  866. char *body;
  867. {
  868.     NameNode *nn = malloc(sizeof(NameNode));
  869.  
  870.     nn->n_In = opt;
  871.     nn->n_Out= body;
  872.     AddTail(list, &nn->n_Node);
  873. }
  874.  
  875. char *
  876. Tailer(ptr)
  877. char *ptr;
  878. {
  879.     short i;
  880.  
  881.     for (i = strlen(ptr) - 1; i >= 0 && ptr[i] != '.'; --i);
  882.     if (i < 0)
  883.     return("");
  884.     return(ptr + i + 1);
  885. }
  886.  
  887. char *
  888. XFilePart(ptr)
  889. char *ptr;
  890. {
  891.     short i;
  892.  
  893.     for (i = strlen(ptr) - 1; i >= 0 && ptr[i] != ':' && ptr[i] != '/'; --i);
  894.     ++i;
  895.     return(ptr + i);
  896. }
  897.  
  898. char *
  899. OptListToStr(list)
  900. LIST *list;
  901. {
  902.     static char Tmp[512];
  903.     short i;
  904.     NameNode *scan;
  905.  
  906.     i = 0;
  907.     Tmp[0] = 0;
  908.     for (scan = (NameNode *)list->lh_Head; scan != (NameNode *)&list->lh_Tail; scan = (NameNode *)scan->n_Node.ln_Succ) {
  909.     sprintf(Tmp + i, " %s%s", scan->n_In, scan->n_Out);
  910.     i += strlen(Tmp + i);
  911.     }
  912.     return(Tmp);
  913. }
  914.  
  915. #ifdef AZLAT_COMPAT
  916.  
  917. char *
  918. OptListToStr2(list, cvt)
  919. LIST *list;
  920. char *cvt;
  921. {
  922.     static char Tmp[512];
  923.     short i;
  924.     NameNode *scan;
  925.  
  926.     i = 0;
  927.     for (scan = (NameNode *)list->lh_Head; scan != (NameNode *)&list->lh_Tail; scan = (NameNode *)scan->n_Node.ln_Succ) {
  928.     sprintf(Tmp + i, " %s%s", scan->n_In, scan->n_Out);
  929.     {
  930.         char *ptr;
  931.         for (ptr = cvt; *ptr; ptr += 2) {
  932.         if (Tmp[i+2] == ptr[0])
  933.             Tmp[i+2] = ptr[1];
  934.         }
  935.     }
  936.     i += strlen(Tmp + i);
  937.     }
  938.     return(Tmp);
  939. }
  940.  
  941. #endif
  942.  
  943. /*
  944.  *  run_cmd(buf)        buf[-1] is valid for BCPL stuff, buf[-1] is
  945.  *            long word aligned.
  946.  */
  947.  
  948. void
  949. run_cmd(buf)
  950. char *buf;
  951. {
  952.     short i;
  953.     short j = strlen(buf);
  954.     int r;
  955.  
  956.     if (Verbose)
  957.     printf("%s\n", buf);
  958.  
  959.     if (ErrFile)
  960.     fclose(stderr);
  961.  
  962. #if INCLUDE_VERSION >= 36
  963.     if (SysBase->lib_Version >= 36) {
  964.     long seg;
  965.     long lock;
  966.     char c;
  967.  
  968.     Process *proc = FindTask(NULL);
  969.     CLI *cli = BTOC(proc->pr_CLI, CLI);
  970.     long oldCommandName;
  971.  
  972.     if (DDebug)
  973.         puts("cmd-begin");
  974.  
  975.     for (i = 0; buf[i] && buf[i] != ' '; ++i);
  976.     c = buf[i];
  977.     buf[i] = 0;
  978.  
  979.     if (cli) {
  980.         oldCommandName = (long)cli->cli_CommandName;
  981.         buf[-1] = i;
  982.         cli->cli_CommandName = CTOB(buf - 1);
  983.     }
  984.  
  985.     if (seg = FindSegment(buf, 0L, 0)) {
  986.         r = RunCommand(((long *)seg)[2], 8192, buf + i + 1, strlen(buf + i + 1));
  987.     } else if ((lock = _SearchPath(buf)) && seg = LoadSegLock(lock)) {
  988.         r = RunCommand(seg, 8192, buf + i + 1, strlen(buf + i + 1));
  989.         UnLoadSeg(seg);
  990.     } else {
  991.         buf[i] = c;
  992.         r = System(buf, NULL);
  993.     }
  994.     if (cli)
  995.         cli->cli_CommandName = (BSTR)oldCommandName;
  996.  
  997.     if (DDebug)
  998.         puts("cmd-end");
  999.     } else {
  1000. #else
  1001.     {
  1002. #endif
  1003.  
  1004. #ifdef _DCC
  1005.     if (FastOpt == 0) {
  1006. #endif
  1007.         if (Execute(buf, NULL, Output()) != -1) {
  1008.         printf("Unable to Execute %s\n", buf);
  1009.         exit(1);
  1010.         }
  1011.         r = 0;
  1012. #ifdef NOTDEF
  1013.         r = IoErr();
  1014.         if (r && r != -1) {
  1015.         puts("Non-Zero exit code");
  1016.         exit(1);
  1017.         }
  1018. #endif
  1019.  
  1020. #ifdef _DCC
  1021.     } else {
  1022.         for (i = 0; buf[i] && buf[i] != ' '; ++i);
  1023.         buf[i] = 0;
  1024.         if (i != j) {
  1025.         for (++i; buf[i] == ' '; ++i);
  1026.         }
  1027.         r = exec_dcc(buf, buf + i);
  1028.     }
  1029. #endif
  1030.     }
  1031.     if (r) {
  1032.     printf("Exit code %d\n", r);
  1033.     exit(1);
  1034.     }
  1035.     if (ErrFile)
  1036.     freopen(ErrFile, "a", stderr);
  1037. }
  1038.  
  1039. int
  1040. OutOfDate(in, out)
  1041. char *in;
  1042. char *out;
  1043. {
  1044.     static FIB *InFib;
  1045.     static FIB *OutFib;
  1046.     BPTR inLock, outLock;
  1047.     FIB *inFib;
  1048.     FIB *outFib;
  1049.     int r = 1;
  1050.  
  1051.     if (NewOpt == 0)
  1052.     return(1);
  1053.  
  1054.     if (InFib == NULL) {
  1055.     InFib = malloc(sizeof(FIB));
  1056.     OutFib = malloc(sizeof(FIB));
  1057.     }
  1058.     inFib = InFib;
  1059.     outFib = OutFib;
  1060.  
  1061.     if (inLock = Lock(in, SHARED_LOCK)) {
  1062.     if (outLock = Lock(out, SHARED_LOCK)) {
  1063.         if (Examine(inLock, inFib) && Examine(outLock, outFib)) {
  1064.         if (inFib->fib_Date.ds_Days < outFib->fib_Date.ds_Days)
  1065.             r = 0;
  1066.         else if (inFib->fib_Date.ds_Days == outFib->fib_Date.ds_Days) {
  1067.             if (inFib->fib_Date.ds_Minute < outFib->fib_Date.ds_Minute)
  1068.             r = 0;
  1069.             else if (inFib->fib_Date.ds_Minute == outFib->fib_Date.ds_Minute) {
  1070.             if (inFib->fib_Date.ds_Tick < outFib->fib_Date.ds_Tick)
  1071.                 r = 0;
  1072.             }
  1073.         }
  1074.         }
  1075.         UnLock(outLock);
  1076.     }
  1077.     UnLock(inLock);
  1078.     }
  1079.     return(r);
  1080. }
  1081.  
  1082. void
  1083. HandleCFile(in, fc)
  1084. char *in;
  1085. int fc;
  1086. {
  1087.     char *asmName;
  1088.     char *objName;
  1089.  
  1090.     if (fc == 1 && OutFile && NoAsm)
  1091.     asmName = OutFile;
  1092.     else
  1093.     asmName = MungeFile(XFilePart(in), TmpDir, ".a");
  1094.  
  1095.     if (fc == 1 && OutFile && NoLink)
  1096.     objName = OutFile;
  1097.     else
  1098.     objName = MungeFile(in, OutDir, ".o");
  1099.  
  1100.     if (NoAsm) {        /*  in -> asmName           */
  1101.     if (OutOfDate(in, asmName))
  1102.         DoCompile(in, asmName);
  1103.     } else {        /*  in -> asmName -> objName*/
  1104.     if (OutOfDate(in, objName)) {
  1105.         PushTmpFile(asmName);
  1106.         if (NoIntermediateAssembly) {
  1107.         DoCompile(in, objName);
  1108.         } else {
  1109.         DoCompile(in, asmName);
  1110.         if (NoHeirOpt == 0)
  1111.             CreateObjPath(objName);
  1112.         DoAssemble(asmName, objName);
  1113.         }
  1114.         PopTmpFile(asmName);
  1115.         remove(asmName);
  1116.     }
  1117.     }
  1118.     AddName(&OList, NULL, objName);
  1119. }
  1120.  
  1121. void
  1122. HandleAFile(in, fc)
  1123. char *in;
  1124. int fc;
  1125. {
  1126.     char *objName;
  1127.  
  1128.     if (fc == 1 && OutFile && NoLink)
  1129.     objName = OutFile;
  1130.     else
  1131.     objName = MungeFile(in, OutDir, ".o");
  1132.  
  1133.     if (OutOfDate(in, objName)) {
  1134.     if (NoHeirOpt == 0)
  1135.         CreateObjPath(objName);
  1136.     DoAssemble(in, objName);
  1137.     }
  1138.     AddName(&OList, NULL, objName);
  1139. }
  1140.  
  1141. void
  1142. PushTmpFile(name)
  1143. char *name;
  1144. {
  1145.     NODE *node = malloc(sizeof(NODE) + strlen(name) + 1);
  1146.     if (node == NULL) {
  1147.     puts("Ran out of memory!");
  1148.     exit(1);
  1149.     }
  1150.     node->ln_Name = (char *)(node + 1);
  1151.     strcpy(node->ln_Name, name);
  1152.     AddHead(&TmpList, node);
  1153. }
  1154.  
  1155. void
  1156. PopTmpFile(name)
  1157. char *name;
  1158. {
  1159.     NODE *node = RemHead(&TmpList);
  1160.  
  1161.     if (node == NULL || strcmp(name, node->ln_Name) != 0) {
  1162.     puts("PopTmpFile: software error");
  1163.     exit(1);
  1164.     }
  1165.     free(node);
  1166. }
  1167.  
  1168. LoadSegLock(lock)
  1169. long lock;
  1170. {
  1171.     long oldLock;
  1172.     long seg;
  1173.  
  1174.     oldLock = CurrentDir(lock);
  1175.     seg = LoadSeg("");
  1176.     CurrentDir(oldLock);
  1177.     return(seg);
  1178. }
  1179.  
  1180. /*
  1181.  *    AZTEC C, LATTICE C COMPATIBILITY OPTIONS
  1182.  */
  1183.  
  1184. #ifdef AZLAT_COMPAT
  1185.  
  1186. DoLink(lfile)
  1187. char *lfile;
  1188. {
  1189.     switch(CompilerOpt) {
  1190.     case DICE_C:
  1191.     return(DoLink_Dice(lfile));
  1192.     case LATTICE_C:
  1193.     return(DoLink_Lattice(lfile));
  1194.     case AZTEC_C:
  1195.     return(DoLink_Aztec(lfile));
  1196.     }
  1197. }
  1198.  
  1199. DoCompile(in, out)
  1200. char *in;
  1201. char *out;
  1202. {
  1203.     switch(CompilerOpt) {
  1204.     case DICE_C:
  1205.     return(DoCompile_Dice(in, out));
  1206.     case LATTICE_C:
  1207.     return(DoCompile_Lattice(in, out));
  1208.     case AZTEC_C:
  1209.     return(DoCompile_Aztec(in, out));
  1210.     }
  1211.     return(0);
  1212. }
  1213.  
  1214. DoAssemble(in, out)
  1215. char *in;
  1216. char *out;
  1217. {
  1218.     switch(CompilerOpt) {
  1219.     case DICE_C:
  1220.     return(DoAssemble_Dice(in, out));
  1221.     case LATTICE_C:
  1222.     return(DoAssemble_Lattice(in, out));
  1223.     case AZTEC_C:
  1224.     return(DoAssemble_Aztec(in, out));
  1225.     }
  1226.     return(0);
  1227. }
  1228.  
  1229. char *
  1230. DoPrelink(void)
  1231. {
  1232.     switch(CompilerOpt) {
  1233.     case DICE_C:
  1234.     return(DoPrelink_Dice());
  1235.     case LATTICE_C:
  1236.     return(DoPrelink_Lattice());
  1237.     case AZTEC_C:
  1238.     return(DoPrelink_Aztec());
  1239.     }
  1240.     return(0);
  1241. }
  1242.  
  1243. /*
  1244.  *    ------------------------------------------------------------------
  1245.  */
  1246.  
  1247. DoCompile_Lattice(in, out)
  1248. char *in;
  1249. char *out;
  1250. {
  1251.     char *qq = "";
  1252.     char *cptmp = TmpFileName(".i");
  1253.     char *data = (SmallData) ? qq : " -b0";
  1254.  
  1255.     sprintf(Buf, "lc -o%s %s %s %s",
  1256.     out, OptListToStr2(&CppOptList, "DdIi"), data, in
  1257.     );
  1258.     run_cmd(Buf);
  1259.  
  1260.     free(cptmp);
  1261.     return(0);
  1262. }
  1263.  
  1264. DoAssemble_Lattice(in, out)
  1265. char *in;
  1266. char *out;
  1267. {
  1268.     sprintf(Buf, "asm -o%s %s", out, in);
  1269.     run_cmd(Buf);
  1270.     return(0);
  1271. }
  1272.  
  1273. char *
  1274. DoPrelink_Lattice(void)
  1275. {
  1276.     NameNode *nn;
  1277.     char *ltmp = TmpFileName(".lnk");
  1278.     FILE *fi = fopen(ltmp, "w");
  1279.     short libs = 0;
  1280.  
  1281.     if (fi == NULL) {
  1282.     fprintf(stderr, "couldn't create %s\n", ltmp);
  1283.     exit(1);
  1284.     }
  1285.  
  1286.     while (nn = (NameNode *)RemHead(&OList)) {
  1287.     fputs(nn->n_In, fi);
  1288.     putc('\n', fi);
  1289.     }
  1290.  
  1291.     while (nn = (NameNode *)RemHead(&LList)) {
  1292.     if (libs == 0) {
  1293.         fprintf(fi, "LIB ");
  1294.         libs = 1;
  1295.     }
  1296.     fputs(nn->n_In, fi);
  1297.     putc('\n', fi);
  1298.     }
  1299.     if (RomOpt == 0 && NoDefaultLibs == 0) {
  1300.     if (libs == 0) {
  1301.         fprintf(fi, "LIB ");
  1302.         libs = 1;
  1303.     }
  1304.     fprintf(fi, "lib:lc.lib lib:amiga.lib\n");
  1305.     }
  1306.  
  1307.     fclose(fi);
  1308.     return(ltmp);
  1309. }
  1310.  
  1311. DoLink_Lattice(lfile)
  1312. char *lfile;
  1313. {
  1314.     char *qq = "";
  1315.     char *co = " ";
  1316.     char *symopt = (SymOpt) ? " ADDSYM" : qq;
  1317.     char *scopt = (SmallData) ? " SD" : qq;
  1318.     char *sdopt = (SmallCode) ? " SC" : qq;
  1319.  
  1320.     if (RomOpt == 0 && NoDefaultLibs == 0) {       /*  RomOpt PIOpt ResOpt */
  1321.     static char *SCode[] = { "lib:c.o",         /*    0      0      0   */
  1322.                  "lib:cres.o",      /*    0      0      1   */
  1323.                  "lib:c.o",         /*    0      1      0   */
  1324.                  "lib:cres.o"       /*    0      1      1   */
  1325.                    };
  1326.     co = SCode[(short)((PIOpt << 1) | ResOpt)];
  1327.     }
  1328.  
  1329.     if (OutFile == NULL)
  1330.     OutFile = "a.out";
  1331.  
  1332.     sprintf(Buf, "BLink from %s with %s to %s%s%s%s",
  1333.     co, lfile, OutFile, symopt, scopt, sdopt
  1334.     );
  1335.     run_cmd(Buf);
  1336.     return(0);
  1337. }
  1338.  
  1339. /*
  1340.  *  ---------------------------------------------------------------------
  1341.  */
  1342.  
  1343. DoCompile_Aztec(in, out)
  1344. char *in;
  1345. char *out;
  1346. {
  1347.     char *qq = "";
  1348.     char *cptmp = TmpFileName(".i");
  1349.     char *data = (SmallData) ? qq : qq;
  1350.  
  1351.     sprintf(Buf, "cc %s %s %s -o %s",
  1352.     OptListToStr2(&CppOptList, ""), data, in, out
  1353.     );
  1354.     run_cmd(Buf);
  1355.  
  1356.     free(cptmp);
  1357.     return(0);
  1358. }
  1359.  
  1360. DoAssemble_Aztec(in, out)
  1361. char *in;
  1362. char *out;
  1363. {
  1364.     sprintf(Buf, "as %s -o %s", in, out);
  1365.     run_cmd(Buf);
  1366.     return(0);
  1367. }
  1368.  
  1369. char *
  1370. DoPrelink_Aztec(void)
  1371. {
  1372.     NameNode *nn;
  1373.     char *ltmp = TmpFileName(".lnk");
  1374.     FILE *fi = fopen(ltmp, "w");
  1375.  
  1376.     if (fi == NULL) {
  1377.     fprintf(stderr, "couldn't create %s\n", ltmp);
  1378.     exit(1);
  1379.     }
  1380.  
  1381.     while (nn = (NameNode *)RemHead(&OList)) {
  1382.     fputs(nn->n_In, fi);
  1383.     putc('\n', fi);
  1384.     }
  1385.     while (nn = (NameNode *)RemHead(&LList)) {
  1386.     fputs(nn->n_In, fi);
  1387.     putc('\n', fi);
  1388.     }
  1389.     if (RomOpt == 0 && NoDefaultLibs == 0) {
  1390.     fprintf(fi, "-lc\n");
  1391.     }
  1392.     fclose(fi);
  1393.     return(ltmp);
  1394. }
  1395.  
  1396. DoLink_Aztec(lfile)
  1397. char *lfile;
  1398. {
  1399.     char *qq = "";
  1400.  
  1401.     if (OutFile == NULL)
  1402.     OutFile = "a.out";
  1403.  
  1404.     sprintf(Buf, "ln -f %s -o %s", lfile, OutFile);
  1405.     run_cmd(Buf);
  1406.     return(0);
  1407. }
  1408.  
  1409. #endif
  1410.  
  1411.